package cg.studio.algorithm.collection;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class CircularQueue<E> implements Queue<E>
{
  private E[] elements;
  private int head = -1;  // first element, pop element
  private int tail = -1;  // last element, put element;
  private ReadWriteLock rwLock = new ReentrantReadWriteLock(); 
  
  @SuppressWarnings( "unchecked")
  public CircularQueue( int capacity )
  {
    if( capacity <= 0 )
      throw new IllegalArgumentException( "expecting capacity large than 0." );
    elements = (E[])new Object[ capacity ];
  }
  
  public boolean add( E element )
  {
    if( isFull() )
      return false;
    
    rwLock.writeLock().lock();
          
    tail = next( tail );
    elements[tail] = element;
    if( head == -1 )
      head = 0;
    rwLock.writeLock().unlock();
    return true;
  }
  
  //pull element from head
  public E poll()
  {
    if( isEmpty() )
      return null;
    
    rwLock.writeLock().lock();
   
    E element = elements[ head ];
    head = next( head );

    rwLock.writeLock().unlock();
    return element;
  }
  
  public E peek()
  {
    if( isEmpty() )
      return null;
    
    rwLock.readLock().lock();
    E element = elements[ head ];
    rwLock.readLock().unlock();
    return element;
  }
  
  protected boolean isFull()
  {
    return ( tail == head + elements.length || tail+1 == head );
  }
  protected boolean isEmpty()
  {
    return ( head<0 || head==tail+1);
  }
  protected int next( int index )
  {
    if( ++index == elements.length )
      return 0;
    return index;
  }
  

}
